package com.interfaces.pay;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.interfaces.config.ProjectConfig;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class WxPay {
    public static String outTradeNoGen(){
        /****************订单号生成*******************/
        Long times=new Date().getTime();
        LocalDateTime now = LocalDateTime.now();
        // 创建一个DateTimeFormatter实例，指定日期和时间的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        // 使用formatter格式化当前日期和时间
        String formattedDateTime = now.format(formatter);
        StringBuffer outTradeNoStr=new StringBuffer("WX");
        outTradeNoStr.append(formattedDateTime);
        String timesStr=times.toString();
        String timesStr6=timesStr.substring(timesStr.length()-6,timesStr.length());
        outTradeNoStr.append(timesStr6);
        String outTradeNo=outTradeNoStr.toString();
        /***********************************/
        return outTradeNo;
    }
    public static WxPayUnifiedOrderV3Result.AppResult appApy(String title, String outTradeNo, BigDecimal money){
        money=money.multiply(new BigDecimal(100));
        // 配置微信支付信息
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId(ProjectConfig.WxPayInit.APPID);
        wxPayConfig.setMchId(ProjectConfig.WxPayInit.MCHID);
        wxPayConfig.setMchKey(ProjectConfig.WxPayInit.v3key);
        wxPayConfig.setApiV3Key(ProjectConfig.WxPayInit.v3key);
        wxPayConfig.setKeyPath(ProjectConfig.WxPayInit.keyPath); // 证书路径，如果使用证书
        wxPayConfig.setCertSerialNo(ProjectConfig.WxPayInit.serialNumber);
        wxPayConfig.setPrivateKeyPath(ProjectConfig.WxPayInit.privateKeyPath);
        wxPayConfig.setPrivateCertPath(ProjectConfig.WxPayInit.privateCertPath);
//        wxPayConfig.setSignType("RSA");
        // 创建微信支付服务
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(wxPayConfig);

        // 创建统一下单请求对象
        WxPayUnifiedOrderV3Request orderV3Request=new WxPayUnifiedOrderV3Request();
//        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderV3Request.setDescription(title);
        WxPayUnifiedOrderV3Request.Amount amount=new WxPayUnifiedOrderV3Request.Amount();
        amount.setTotal(money.intValue());
        amount.setCurrency("CNY");
        orderV3Request.setAmount(amount); // 订单总金额，单位为分
        orderV3Request.setOutTradeNo(outTradeNo);
        orderV3Request.setAppid(ProjectConfig.WxPayInit.APPID);
        orderV3Request.setMchid(ProjectConfig.WxPayInit.MCHID);
        orderV3Request.setNotifyUrl(ProjectConfig.WxPayInit.notifyUrl); // 支付结果通知地址
        WxPayUnifiedOrderV3Request.SceneInfo sceneInfo=new WxPayUnifiedOrderV3Request.SceneInfo();
        sceneInfo.setPayerClientIp("101.37.20.4");
        orderV3Request.setSceneInfo(sceneInfo);
        try {
            // 调用统一下单接口
            WxPayUnifiedOrderV3Result result = wxPayService.unifiedOrderV3(TradeTypeEnum.APP,orderV3Request);

            WxPayUnifiedOrderV3Result.AppResult appResult=result.getPayInfo(TradeTypeEnum.APP, ProjectConfig.WxPayInit.APPID, ProjectConfig.WxPayInit.MCHID,wxPayConfig.getPrivateKey());
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL);
            objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
            objectMapper.configure(SerializationFeature.INDENT_OUTPUT, false);
            String body =objectMapper.writeValueAsString(orderV3Request);
            String sign=getSignApp(Long.valueOf(appResult.getTimestamp()),appResult.getNoncestr(), appResult.getPrepayId());
            appResult.setSign(sign);
            Map<String, Object> res=convertFieldsToLowerCase(appResult);
            res.remove("serialversionuid");
            res.put("package",res.get("packagevalue"));
            res.remove("packagevalue");
            return appResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    public static Map<String, Object> convertFieldsToLowerCase(Object obj) {
        Map<String, Object> result = new HashMap<>();
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true); // 设置私有字段也可访问
            try {
                String key = field.getName().toLowerCase(); // 将字段名转换为小写
                result.put(key, field.get(obj)); // 获取字段值并放入Map
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    public static String getSignApp(long timestamp, String nonceStr, String prepayId) {
        StringBuilder signContent = new StringBuilder();
        signContent.append(ProjectConfig.WxPayInit.APPID).append("\n");
        signContent.append(timestamp).append("\n");
        signContent.append(nonceStr).append("\n");
        signContent.append(prepayId).append("\n");
        return sha256sign(signContent.toString());
    }
    public static String sha256sign(String message){
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(getPrivateKey());
            signature.update(message.getBytes());
            //Base64.encode)
            return new String(signature.sign());
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }

    }
    public static PrivateKey getPrivateKey()  {
        try {
            String p12Path=ProjectConfig.WxPayInit.keyPath;
            String p12Password=ProjectConfig.WxPayInit.MCHID;
            // 初始化KeyStore
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            try (InputStream is = new FileInputStream(p12Path)) {
                keyStore.load(is, p12Password.toCharArray()); // 加载p12文件
            }

            // 获取私钥的别名，通常别名是证书的别名
            String keyAlias = keyStore.aliases().nextElement(); // 通常只有一个条目，即私钥条目
            PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, p12Password.toCharArray());
            return privateKey;
        }catch (Exception e){
            System.err.println("P12证书加载异常");
            throw new RuntimeException(e.getMessage());
        }
    }
}
